home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
programming
/
other
/
jikes
/
src
/
parser.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
24KB
|
785 lines
// $Id: parser.cpp,v 1.3 1999/01/25 20:00:31 shields Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#include "config.h"
#include <assert.h>
#include <iostream.h>
#include "parser.h"
#include "ast.h"
void Parser::ReallocateStacks()
{
int old_stack_length = stack_length;
stack_length += STACK_INCREMENT;
assert(stack_length <= SHRT_MAX);
int *old_stack = stack;
stack = (int *) memmove(new int[stack_length], stack, old_stack_length * sizeof(int));
delete [] old_stack;
Location *old_location_stack = location_stack;
location_stack = (Location *) memmove(new Location[stack_length], location_stack, old_stack_length * sizeof(Location));
delete [] old_location_stack;
Ast **old_parse_stack = parse_stack;
parse_stack = (Ast **) memmove(new Ast *[stack_length], parse_stack, old_stack_length * sizeof(Ast *));
delete [] old_parse_stack;
parse_stack[old_stack_length] = NULL; // the first time through, we initialize parse_stack[0] to NULL !!!
int *old_temp_stack = temp_stack;
temp_stack = (int *) memmove(new int[stack_length], temp_stack, old_stack_length * sizeof(int));
delete [] old_temp_stack;
return;
}
AstListNode *Parser::AllocateListNode()
{
AstListNode *p;
if (free_list_nodes)
{
p = free_list_nodes;
free_list_nodes = free_list_nodes -> next;
}
else p = list_node_pool -> NewListNode();
return p;
}
void Parser::FreeCircularList(AstListNode *tail)
{
AstListNode *root = tail -> next;
tail -> next = free_list_nodes;
free_list_nodes = root;
return;
}
AstPackageDeclaration *Parser::PackageHeaderParse(LexStream *lex_stream_, StoragePool *ast_pool_)
{
AstPackageDeclaration *package_declaration = NULL;
lex_stream_ -> Reset();
if (lex_stream_ -> Kind(lex_stream_ -> Peek()) == TK_package)
{
ast_pool = ast_pool_;
parse_package_header_only = true;
end_token = LexStream::INFINITY; // We are parsing the whole input and not just a segment.
lex_stream = lex_stream_;
Ast *ast = HeaderParse();
parse_package_header_only = false;
if (ast)
{
AstCompilationUnit *compilation_unit = ast -> CompilationUnitCast();
if (compilation_unit && (! compilation_unit -> BadCompilationUnitCast()))
package_declaration = compilation_unit -> package_declaration_opt;
}
}
return package_declaration;
}
AstCompilationUnit *Parser::HeaderParse(LexStream *lex_stream_, StoragePool *ast_pool_)
{
lex_stream_ -> Reset();
body_pool = new StoragePool(lex_stream_ -> NumTokens());
ast_pool = (ast_pool_ ? ast_pool_ : body_pool);
list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
free_list_nodes = NULL;
AstCompilationUnit *compilation_unit = NULL;
parse_header_only = true;
end_token = LexStream::INFINITY; // We are parsing the whole input and not just a segment.
lex_stream = lex_stream_;
Ast *ast = HeaderParse();
parse_header_only = false;
if (ast)
{
compilation_unit = ast -> CompilationUnitCast();
if (compilation_unit && (! compilation_unit -> BadCompilationUnitCast()))
{
if (compilation_unit -> NumTypeDeclarations() == 0)
compilation_unit -> kind = Ast::EMPTY_COMPILATION;
}
// STG:
// else delete ast;
//
}
//
// If we succesfully parsed a compilation unit, allocate a storage pool for it.
// Subtract the amount of space that's already been allocated for the headers
// from the estimate for the bodies.
//
if (compilation_unit)
compilation_unit -> ast_pool = body_pool;
else delete body_pool;
delete list_node_pool; // free the pool of list nodes
return compilation_unit;
}
Ast *Parser::HeaderParse()
{
TokenObject curtok = lex_stream -> Gettoken();
int act = START_STATE,
current_kind = lex_stream -> Kind(curtok);
/*****************************************************************/
/* Start parsing. */
/*****************************************************************/
state_stack_top = -1;
//
// Process a terminal
//
for (;;)
{
if (++state_stack_top >= stack_length)
ReallocateStacks();
stack[state_stack_top] = act;
location_stack[state_stack_top] = Loc(curtok);
act = t_action(act, current_kind, lex_stream);
if (act <= NUM_RULES)
state_stack_top--; // make reduction look like a shift-reduce
else if (act > ERROR_ACTION)
{
// STG:
// token_action(curtok);
curtok = lex_stream -> Gettoken();
current_kind = lex_stream -> Kind(curtok);
act -= ERROR_ACTION;
}
else if (act < ACCEPT_ACTION)
{
// STG:
// token_action(curtok);
curtok = lex_stream -> Gettoken();
current_kind = lex_stream -> Kind(curtok);
continue;
}
else break;
//
// Process a non_terminal
//
do
{
state_stack_top -= (rhs[act] - 1);
(this ->* rule_action[act])();
act = nt_action(stack[state_stack_top], lhs[act]);
} while(act <= NUM_RULES);
} /* process_terminal */
if (act == ERROR_ACTION)
{
//
// If any error is found in a package declaration, do not try to repair it.
//
if (! parse_package_header_only)
RepairParse(curtok);
if (parse_stack[0] && parse_stack[0] -> CompilationUnitCast())
parse_stack[0] -> kind = Ast::BAD_COMPILATION;
else
{
// STG:
// delete parse_stack[0];
parse_stack[0] = NULL;
}
}
return parse_stack[0];
}
bool Parser::BodyParse(LexStream *lex_stream_, AstClassBody *class_body)
{
assert(class_body -> UnparsedClassBodyCast());
lex_stream = lex_stream_;
ast_pool = class_body -> pool;
body_pool = class_body -> pool;
list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
free_list_nodes = NULL;
bool no_errors_detected = Body(class_body);
delete list_node_pool; // free the pool of list nodes
class_body -> mark_parsed();
return no_errors_detected;
}
bool Parser::Body(AstClassBody *class_body)
{
bool no_errors_detected = true;
for (int i = 0; i < class_body -> NumConstructors(); i++)
{
AstConstructorDeclaration *constructor_decl = class_body -> Constructor(i);
if (constructor_decl -> constructor_symbol)
{
AstConstructorBlock *block = constructor_decl -> constructor_body;
end_token = block -> right_brace_token; // last token in the body
AstStatement *new_body = (AstStatement *) ParseSegment(block -> left_brace_token);
if (! new_body)
no_errors_detected = false;
else
{
AstConstructorBlock *new_block = new_body -> ConstructorBlockCast();
if (! new_block)
{
new_block = ast_pool -> GenConstructorBlock();
new_block -> left_brace_token = new_body -> LeftToken();
new_block -> explicit_constructor_invocation_opt = NULL;
new_block -> block = (AstBlock *) new_body;
new_block -> right_brace_token = new_body -> RightToken();
}
// STG:
// delete block; // destroy old empty block
//
constructor_decl -> constructor_body = new_block;
}
}
}
for (int j = 0; j < class_body ->